package com.tinem.platform.web.gateway.exception;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import com.tinem.platform.module.pojo.co.GatewayHeadName;
import com.tinem.platform.module.pojo.co.RedisKeyEnum;
import com.tinem.platform.module.pojo.vo.error.PlatformException;
import com.tinem.platform.module.starter.sdk.MessageCode;
import com.tinem.platform.web.gateway.util.MDCUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.context.MessageSource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Locale;

@Slf4j
public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {

    @Resource
    MessageSource messageSource;

    @Resource
    StringRedisTemplate stringRedisTemplate;

    public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
                                ErrorProperties errorProperties, ApplicationContext applicationContext) {
        super(errorAttributes, resourceProperties, errorProperties, applicationContext);
    }

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable throwable) {
        MDCUtil.set(exchange);
        log.error("error",throwable);
        exchange.getResponse().setStatusCode(HttpStatus.OK);
        exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_SUCCES,"false");
        if(throwable instanceof PlatformException){
            MessageCode code = ((PlatformException) throwable).getCode();
            exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_CODE,code.name());
            String l = exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_LANG);
            Locale lang = StrUtil.isEmpty(l)?Locale.getDefault():Locale.forLanguageTag(l);
            exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_MESSAGE, Base64.encode(code.getMessage(lang,((PlatformException) throwable).getArgs())));
        }else if(throwable instanceof IllegalStateException && "not obtain the keys".equals(throwable.getMessage())){
            exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_CODE,MessageCode.ERROR_COMMONS_SERVER.name());
            String l = exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_LANG);
            Locale lang = StrUtil.isEmpty(l)?Locale.getDefault():Locale.forLanguageTag(l);
            exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_MESSAGE, Base64.encode(MessageCode.ERROR_COMMONS_SERVER.getMessage(lang,"platform-cloud-web-auth")));
        }else{
            exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_CODE,MessageCode.ERROR_COMMONS_UNKNOWN.name());
            String l = exchange.getRequest().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_REQ_LANG);
            Locale lang = StrUtil.isEmpty(l)?Locale.getDefault():Locale.forLanguageTag(l);
            exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_MESSAGE, Base64.encode(MessageCode.ERROR_COMMONS_UNKNOWN.getMessage(lang,StrUtil.format("{}:{}",throwable.getClass().getName(),throwable.getMessage()))));
        }
        exchange.getResponse().getHeaders().set(GatewayHeadName.X_PLATFORM_GATEWAY_RES_TIMESTAMP,System.currentTimeMillis()+"");
        log.error(" code: ({}); message: ({})"
                ,exchange.getResponse().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_RES_CODE)
                ,exchange.getResponse().getHeaders().getFirst(GatewayHeadName.X_PLATFORM_GATEWAY_RES_MESSAGE)
        );
        
        String gatewayRequestId = exchange.getAttribute(GatewayHeadName.X_PLATFORM_GATEWAY_REQUEST_ID);
        if(StrUtil.isEmpty(gatewayRequestId)){
            return Mono.empty();
        }
        //请求处理完成，插入处理队列
        log.info("request info to redis query.");
        stringRedisTemplate.opsForList().rightPush(RedisKeyEnum.gateway_req_info_query.getKey(),gatewayRequestId);
        return Mono.empty();
    }
}